import os
import json
import random
import logging
from flask import Flask, request, jsonify, session, send_from_directory
from flask_cors import CORS
from flask_socketio import SocketIO, join_room, leave_room, emit
# 确保不使用eventlet
os.environ['FLASK_SOCKETIO_ASYNC_MODE'] = 'threading'
import time
from models import Database

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger('app')

# 获取当前脚本所在目录的父目录（即kousuangame目录）
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_DIR = os.path.join(BASE_DIR, 'static')
app = Flask(__name__, static_folder=STATIC_DIR)
app.config['SECRET_KEY'] = 'your-secret-key'
# 配置CORS以允许所有来源访问
CORS(app, origins="*")
socketio = SocketIO(app, cors_allowed_origins="*", async_mode='threading')

# 添加默认路由以提供HTML页面
@app.route('/')
def index():
    return app.send_static_file('multiplayer.html')

# 添加错误处理，确保API返回JSON而不是HTML错误页面
@app.errorhandler(404)
def not_found(error):
    logger.warning(f'404 Not Found: {request.path}')
    if request.path.startswith('/api/'):
        response = jsonify({'success': False, 'message': 'API端点不存在'})
        response.headers['Content-Type'] = 'application/json'
        return response, 404
    # 对于非API请求，尝试提供静态文件，如果不存在则返回multiplayer.html
    if os.path.exists(os.path.join(STATIC_DIR, request.path.lstrip('/'))):
        return send_from_directory(STATIC_DIR, request.path.lstrip('/'))
    return app.send_static_file('multiplayer.html')

# 初始化数据库
db = Database()

# 游戏状态管理
waiting_players = []
active_games = {}

# 生成题目
def generate_question(grade=3):
    if grade == 1:
        a = random.randint(1, 10)
        b = random.randint(1, 10)
        op = random.choice(['+', '-'])
        if op == '-':
            a, b = max(a, b), min(a, b)
        question = f"{a} {op} {b} = ?"
        answer = str(a + b if op == '+' else a - b)
    elif grade == 2:
        a = random.randint(1, 20)
        b = random.randint(1, 20)
        op = random.choice(['+', '-', '*'])
        if op == '-':
            a, b = max(a, b), min(a, b)
        elif op == '*':
            a = random.randint(1, 10)
            b = random.randint(1, 10)
        question = f"{a} {op} {b} = ?"
        answer = str(a + b if op == '+' else (a - b if op == '-' else a * b))
    else:  # 3-6年级
        a = random.randint(1, 50)
        b = random.randint(1, 50)
        op = random.choice(['+', '-', '*', '/'])
        if op == '-':
            a, b = max(a, b), min(a, b)
        elif op == '/':
            # 确保除法结果是整数
            b = random.randint(1, 10)
            a = b * random.randint(1, 10)
        question = f"{a} {op} {b} = ?"
        answer = str(a + b if op == '+' else (a - b if op == '-' else (a * b if op == '*' else a // b)))
    
    return question, answer

# API路由
@app.route('/api/register', methods=['POST'])
def register():
    data = request.json
    username = data.get('username')
    password = data.get('password')
    
    if not username or not password:
        response = jsonify({'success': False, 'message': '用户名和密码不能为空'})
        response.headers['Content-Type'] = 'application/json'
        return response, 400
    
    success, message = db.register_user(username, password)
    response = jsonify({'success': success, 'message': message})
    response.headers['Content-Type'] = 'application/json'
    return response

@app.route('/api/login', methods=['POST'])
def login():
    data = request.json
    username = data.get('username')
    password = data.get('password')
    
    if not username or not password:
        response = jsonify({'success': False, 'message': '用户名和密码不能为空'})
        response.headers['Content-Type'] = 'application/json'
        return response, 400
    
    success, user_data, message = db.login_user(username, password)
    if success:
        response = jsonify({'success': True, 'message': message, 'user': user_data})
        response.headers['Content-Type'] = 'application/json'
        return response
    else:
        response = jsonify({'success': False, 'message': message})
        response.headers['Content-Type'] = 'application/json'
        return response

@app.route('/api/user/<int:user_id>', methods=['GET'])
def get_user_info(user_id):
    user_info = db.get_user_info(user_id)
    if user_info:
        response = jsonify({'success': True, 'user': user_info})
        response.headers['Content-Type'] = 'application/json'
        return response
    else:
        response = jsonify({'success': False, 'message': '用户不存在'})
        response.headers['Content-Type'] = 'application/json'
        return response, 404

@app.route('/api/leaderboard', methods=['GET'])
def get_leaderboard():
    try:
        logger.info(f'API Request: GET /api/leaderboard with params: {request.args}')
        # 获取查询参数，默认为40
        limit = request.args.get('limit', 40, type=int)
        # 限制最大值为100，避免查询过多数据
        limit = min(limit, 100)
        
        leaderboard = db.get_leaderboard(limit)
        logger.info(f'Leaderboard data retrieved, count: {len(leaderboard)}')
        response = jsonify({'success': True, 'leaderboard': leaderboard})
        response.headers['Content-Type'] = 'application/json'
        logger.info('API Response: GET /api/leaderboard - 200 OK')
        return response
    except Exception as e:
        logger.error(f'Error in get_leaderboard: {str(e)}')
        response = jsonify({'success': False, 'message': '服务器内部错误'})
        response.headers['Content-Type'] = 'application/json'
        return response, 500

@app.route('/api/user/<int:user_id>/rank', methods=['GET'])
def get_user_rank_info(user_id):
    try:
        logger.info(f'API Request: GET /api/user/{user_id}/rank')
        # 获取用户基本信息
        user_info = db.get_user_info(user_id)
        if not user_info:
            logger.warning(f'User not found: {user_id}')
            response = jsonify({'success': False, 'message': '用户不存在'})
            response.headers['Content-Type'] = 'application/json'
            return response, 404
        
        # 获取用户排名
        rank_info = db.get_user_rank(user_id)
        if rank_info:
            logger.info(f'Rank info retrieved for user {user_id}: rank={rank_info["rank"]}')
            response = jsonify({
                'success': True,
                'user': {
                    'id': user_info['id'],
                    'username': user_info['username'],
                    'points': user_info['points'],
                    'rank': rank_info['rank']
                }
            })
            response.headers['Content-Type'] = 'application/json'
            return response
        else:
            logger.error(f'Failed to get rank for user {user_id}')
            response = jsonify({'success': False, 'message': '获取排名失败'})
            response.headers['Content-Type'] = 'application/json'
            return response, 500
    except Exception as e:
        logger.error(f'Error in get_user_rank_info for user {user_id}: {str(e)}')
        response = jsonify({'success': False, 'message': '服务器内部错误'})
        response.headers['Content-Type'] = 'application/json'
        return response, 500

# WebSocket事件处理
@socketio.on('connect')
def handle_connect():
    print(f'客户端连接: {request.sid}')

@socketio.on('disconnect')
def handle_disconnect():
    # 清理用户状态
    for game_id, game in active_games.items():
        if request.sid in game['players']:
            # 通知另一个玩家对方已断开连接
            other_sid = game['players'][0] if game['players'][1] == request.sid else game['players'][1]
            emit('opponent_disconnected', room=other_sid)
            del active_games[game_id]
            break
    
    # 从等待队列中移除
    global waiting_players
    waiting_players = [p for p in waiting_players if p['sid'] != request.sid]
    print(f'客户端断开: {request.sid}')

@socketio.on('join_queue')
def handle_join_queue(data):
    user_id = data.get('user_id')
    username = data.get('username')
    grade = data.get('grade', 3)
    
    # 将玩家加入等待队列
    waiting_player = {'sid': request.sid, 'user_id': user_id, 'username': username, 'grade': grade}
    waiting_players.append(waiting_player)
    
    # 尝试匹配
    match_players()

@socketio.on('leave_queue')
def handle_leave_queue():
    global waiting_players
    waiting_players = [p for p in waiting_players if p['sid'] != request.sid]

@socketio.on('submit_answer')
def handle_submit_answer(data):
    game_id = data.get('game_id')
    answer = data.get('answer')
    
    if game_id not in active_games:
        return
    
    game = active_games[game_id]
    player_index = game['players'].index(request.sid) if request.sid in game['players'] else -1
    
    if player_index == -1:
        return
    
    # 检查答案是否正确
    is_correct = answer == game['correct_answer']
    
    if is_correct:
        # 更新进度
        game['progress'][player_index] += 1
        
        # 检查游戏是否结束
        if game['progress'][player_index] >= game['total_questions']:
            # 记录获胜者
            winner_id = game['user_ids'][player_index]
            loser_id = game['user_ids'][1 - player_index]
            
            # 发放积分
            db.update_points(winner_id, 15)  # 获胜者加15分
            db.update_points(loser_id, 3)    # 失败者加3分
            
            # 记录游戏结果
            db.record_game_result(
                game['user_ids'][0], 
                game['user_ids'][1], 
                winner_id,
                game['progress'][0],
                game['progress'][1]
            )
            
            # 通知两位玩家游戏结束
            for i, sid in enumerate(game['players']):
                is_winner = i == player_index
                emit('game_over', {
                    'is_winner': is_winner,
                    'winner': game['usernames'][player_index],
                    'loser': game['usernames'][1 - player_index],
                    'your_progress': game['progress'][i],
                    'opponent_progress': game['progress'][1 - i],
                    'points_gained': 15 if is_winner else 3
                }, room=sid)
            
            # 从活跃游戏中移除
            del active_games[game_id]
        else:
            # 生成新题目 - 双方继续同时答题
            question, answer = generate_question(game['grade'])
            game['current_question'] = question
            game['correct_answer'] = answer
            
            # 通知双方玩家状态更新
            for i, sid in enumerate(game['players']):
                emit('game_update', {
                    'your_turn': True,  # 双方都可以答题
                    'question': game['current_question'],
                    'your_progress': game['progress'][i],
                    'opponent_progress': game['progress'][1 - i],
                    'total_questions': game['total_questions'],
                    'opponent_name': game['usernames'][1 - i]
                }, room=sid)
    else:
        # 答案错误，通知当前玩家
        emit('answer_feedback', {
            'correct': False,
            'message': '答案错误，请重试'
        }, room=request.sid)

# 玩家匹配函数
def match_players():
    global waiting_players
    
    # 查找相同年级的玩家进行匹配
    for i in range(len(waiting_players)):
        for j in range(i + 1, len(waiting_players)):
            if waiting_players[i]['grade'] == waiting_players[j]['grade']:
                player1 = waiting_players[i]
                player2 = waiting_players[j]
                
                # 创建游戏房间
                game_id = f"game_{int(time.time())}_{random.randint(1000, 9999)}"
                
                # 生成初始题目
                question, answer = generate_question(player1['grade'])
                
                # 创建游戏 - 双方同时答题
                game = {
                    'id': game_id,
                    'players': [player1['sid'], player2['sid']],
                    'user_ids': [player1['user_id'], player2['user_id']],
                    'usernames': [player1['username'], player2['username']],
                    'grade': player1['grade'],
                    'total_questions': 10,  # 固定10题
                    'progress': [0, 0],
                    'current_question': question,
                    'correct_answer': answer,
                    'start_time': time.time()
                }
                
                active_games[game_id] = game
                
                # 将玩家加入房间
                join_room(game_id, player1['sid'])
                join_room(game_id, player2['sid'])
                
                # 从等待队列中移除
                waiting_players = [p for p in waiting_players if p not in [player1, player2]]
                
                # 通知双方玩家匹配成功，开始倒计时
                for i, player in enumerate([player1, player2]):
                    emit('match_found', {
                        'game_id': game_id,
                        'opponent_name': game['usernames'][1 - i]
                    }, room=player['sid'])
                
                # 3秒后开始游戏
                socketio.start_background_task(start_game_countdown, game_id)
                return

# 游戏开始倒计时
def start_game_countdown(game_id):
    # 3秒倒计时
    for i in range(3, 0, -1):
        socketio.emit('countdown', {'seconds': i}, room=game_id)
        time.sleep(1)
    
    # 开始游戏 - 双方同时开始
    if game_id in active_games:
        game = active_games[game_id]
        for i, sid in enumerate(game['players']):
            socketio.emit('game_start', {
                'your_turn': True,  # 双方都可以答题
                'question': game['current_question'],
                'your_progress': 0,
                'opponent_progress': 0,
                'total_questions': game['total_questions'],
                'opponent_name': game['usernames'][1 - i]
            }, room=sid)

if __name__ == '__main__':
    # 使用threading模式，避免eventlet兼容性问题
    socketio.run(app, host='0.0.0.0', port=5001, debug=True, use_reloader=False)